﻿using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Threading;
using CPL;
namespace PerformanceScalabilityTests
{
    using System;

    /// <summary>
    /// Test for ParallelFor
    /// </summary>
    public class ParallelForPerfomanceTest
    {
        /// <summary>
        /// Empty Constructor
        /// </summary>
        public ParallelForPerfomanceTest()
        {

        }

        /// <summary>
        /// Test Method
        /// </summary>
        public void TestAll()
        {
            CalculationTest();
            //ConcatenationTest();
        }

        #region Calculation

        /// <summary>
        /// Test for Simple Calculations
        /// </summary>
        [MethodImpl(MethodImplOptions.NoOptimization)]
        private void CalculationTest()
        {
            var resulttimelist = new List<double>();
            var random = new Random(DateTime.Now.Millisecond);
            var list = new List<int>();

            for (var i = 0; i < 12; i++)
            {
                list.Add(random.Next(1000));
            }

            for (var parLevel = 1; parLevel <= ParallelSettings.MaxParallelismLevel * 4; parLevel++)
            {
                CalculateParallel(list, resulttimelist, parLevel);
            }
            Helpers help = new Helpers();
            help.WriteLog(resulttimelist);
        }

        /// <summary>
        ///  Calculating for all list
        /// </summary>
        /// <param name="list"></param>
        /// <param name="resulttimelist"></param>
        /// <param name="parLevel"></param>
        [MethodImpl(MethodImplOptions.NoOptimization)]
        private void CalculateParallel(IList<int> list, ICollection<double> resulttimelist, int parLevel)
        {
            Console.Write("Parallelism level: ");
            Console.WriteLine(parLevel);

            var sw = new Stopwatch();
            sw.Start();
            Parallel.For(0, list.Count, 1, parLevel, Calculate);
            sw.Stop();

            Console.WriteLine("Elapsed time :");
            resulttimelist.Add(sw.Elapsed.TotalMilliseconds);
            Console.WriteLine(sw.Elapsed.TotalMilliseconds);
        }

        /// <summary>
        /// Basic calculation
        /// </summary>
        /// <param name="value">Count of Iteration</param>
        [MethodImpl(MethodImplOptions.NoOptimization)]
        private void Calculate(int value)
        {
            Console.Write("Managed thread ID= ");
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
            if (value == 0)
            {
                value = 1;
            }
            for (var i = 0; i < 100000000; i++)
            {
                var d = value * value / value + value;
            }
        }

        #endregion Calculation

        #region Concatination

        /// <summary>
        /// Concatenation test
        /// </summary>
        [MethodImpl(MethodImplOptions.NoOptimization)]
        private void ConcatenationTest()
        {
            var resulttimelist = new List<double>();
            var list = new List<string>();

            for (var i = 0; i < 12; i++)
            {
                list.Add(string.Empty);
            }

            for (var parLevel = 1; parLevel <= ParallelSettings.MaxParallelismLevel * 4; parLevel++)
            {
                ConcatParallel(list, resulttimelist, parLevel);
            }
            Helpers help = new Helpers();
            help.WriteLog(resulttimelist);
        }

        /// <summary>
        ///  Concatenation for all list
        /// </summary>
        /// <param name="list"></param>
        /// <param name="resulttimelist"></param>
        /// <param name="parLevel"></param>
        [MethodImpl(MethodImplOptions.NoOptimization)]
        private void ConcatParallel(IList<string> list, ICollection<double> resulttimelist, int parLevel)
        {
            Console.WriteLine("Parallelism level:");
            Console.WriteLine(parLevel);

            var sw = new Stopwatch();
            sw.Start();
            Parallel.For(0, list.Count, Concat);
            sw.Stop();

            resulttimelist.Add(sw.Elapsed.TotalMilliseconds);
            Console.WriteLine("Elapsed time :");
            Console.WriteLine(sw.Elapsed.TotalMilliseconds);
        }

        /// <summary>
        /// Basic Concatenation
        /// </summary>
        /// <param name="resultstr">String</param>
        [MethodImpl(MethodImplOptions.NoOptimization)]
        private void Concat(int val)
        {
            string resultstr = string.Empty;
            for (var i = 0; i < 30000; i++)
            {
                resultstr += "A";
                resultstr += "B";
                resultstr += "C";
            }
        }

        #endregion Concatination



    }
}